using System.Activities;
using System.Activities.Presentation;
using System.Activities.Presentation.Model;
using System.Activities.Presentation.Services;
using System.Activities.Statements;
using Headsight.BPMN2WF.BPMN.Model;
using Headsight.BPMN2WF.Transformation.Transformers.Additions;
using BPMNFlowNodesBlock = Headsight.BPMN2WF.BPMN.Model.BPMNFlowNodesBlock;

namespace Headsight.BPMN2WF.Transformation
{
    /// <summary>
    /// Current <see cref="IBPMN2WF"/> default implementation.
    /// </summary>
    internal class BPMN2WFImpl : IBPMN2WF
    {
        public BPMN2WFImpl(IBPMN2WFTransformations bpmn2WfTransformations)
        {
            BPMN2WFTransformations = bpmn2WfTransformations;
        }

        public IBPMN2WFTransformations BPMN2WFTransformations { get; private set; }

        public IBPMN2WFResult Transform(BPMNFlowNodesBlock bpmnProcess)
        {
            var workflowDesigner = new WorkflowDesigner();

            var activityBuilder = new ActivityBuilder { Name = bpmnProcess.FullQualifiedName };
            workflowDesigner.Load(activityBuilder);

            var mSrv = workflowDesigner.Context.Services.GetService<ModelService>();
            var mTreeMgr = workflowDesigner.Context.Services.GetService<ModelTreeManager>();

            var ctx = new BPMN2WFTransformationContext
                          {
                              BPMN2WFTransformations = BPMN2WFTransformations,
                              BPMNProcess = bpmnProcess,
                              ModelTreeManager = mTreeMgr,
                              WorkflowDesigner = workflowDesigner
                          };

            var transformed = Transform(ctx, mSrv.Root, bpmnProcess);
            if (mSrv.Root != null)
            {
                var modelProperty = mSrv.Root.Properties["Implementation"];
                if (modelProperty != null)
                    modelProperty.SetValue(transformed);
            }

            return new BPMN2WFResultImpl(workflowDesigner); ;
        }

        private static ModelItem Transform(BPMN2WFTransformationContext ctx, ModelItem modelItemParent, BPMNFlowNode processBlock)
        {
            var transResult = ctx.BPMN2WFTransformations.Get(processBlock).Transform(ctx, processBlock).Result;

            if (!(transResult is Flowchart))
            {
                var flowStep = new FlowStep { Action = transResult };

                var flowchart = new Flowchart { StartNode = flowStep };
                flowchart.Nodes.Add(flowStep);

                transResult = flowchart;
            }
            
            return ctx.ModelTreeManager.CreateModelItem(modelItemParent, transResult);
        }
    }
}